﻿using System;

class Game
{
    private Labyrinth labyrinth;
    private ScoreBoard topScores;
    private int movesCount;

    public Game(Random rand, ScoreBoard scoreBoard)
    {
        labyrinth = new Labyrinth(rand);
        this.topScores = scoreBoard;
        UserIntefrace.PrintWelcomeMessage();
        movesCount = 0;
    }

    private bool TryMove(string direction)
    {
        bool canMove = false;
        switch (direction)
        {
            case "u":
                canMove = labyrinth.TryMove(Direction.Up);
                break;
            case "d":
                canMove = labyrinth.TryMove(Direction.Down);
                break;
            case "l":
                canMove = labyrinth.TryMove(Direction.Left);
                break;
            case "r":
                canMove = labyrinth.TryMove(Direction.Right);
                break;
            default:
                canMove = false;
                break;
        }

        if (canMove == false)
        {
            Console.WriteLine(UserIntefrace.INVALID_MOVE_MSG);
        }
        return canMove;
    }

    public Action ProccessInput(string input, ref int movesCount, ScoreBoard ladder)
    {
        Action returnValue = Action.None;
        string lowerCaseInput = input.ToLower();
        switch (lowerCaseInput)
        {
            case "u":
            case "d":
            case "l":
            case "r":
                //fallthrough
                bool moveDone =
                    TryMove(lowerCaseInput);
                if (moveDone == true)
                {
                    movesCount++;
                    returnValue = Action.Move;
                }
                break;
            case "top":
                ladder.Print();
                returnValue = Action.TopScores;
                break;
            case "exit":
                UserIntefrace.PrintGoodbyeMessage();
                returnValue = Action.Exit;
                break;
            case "restart":
                returnValue = Action.Restart;
                break;
            default:
                UserIntefrace.PrintInvalidCommandMessage();
                returnValue = Action.None;
                break;
        }
        return returnValue;
    }

    public Action Play()
    {
        string input = "";
        Action returnValue = Action.None;

        labyrinth.Print();
        input = UserIntefrace.GetInput();
        returnValue = ProccessInput(input, ref movesCount, topScores);

        if (labyrinth.ExitFound(labyrinth.CurrentCell))
        {

            if (topScores.IsTopScore(movesCount))
            {
                UserIntefrace.PrintScoreBoardInputMessage(movesCount);
                string name = Console.ReadLine();
                topScores.AddResultInScoreboard(movesCount, name);
            }
            returnValue = Action.Restart;
            Console.WriteLine();
        }
        return returnValue;
    }
}

enum Action { Move, TopScores, Exit, Restart, None };
